package com.yl.demo.utils.redis;

import com.yl.demo.base.config.shiro.MyShiroRealm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * redis操作工具类.</br>
 * (基于RedisTemplate)
 * @author YL
 * 2019/10/21
 *
 * spring-data-redis针对jedis提供了如下功能：
 * 1.连接池自动管理，提供了一个高度封装的“RedisTemplate”类
 * 2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
 * ValueOperations：简单K-V操作
 * SetOperations：set类型数据操作
 * ZSetOperations：zset类型数据操作
 * HashOperations：针对map类型的数据操作
 * ListOperations：针对list类型的数据操作
 * redisTemplate.opsForValue(); // 操作字符串
 * redisTemplate.opsForHash(); // 操作hash
 * redisTemplate.opsForList(); // 操作list
 * redisTemplate.opsForSet(); // 操作set
 * redisTemplate.opsForZSet(); // 操作有序set
 *
 * redistempalate.boundValueOps // 操作字符串
 * redistempalate.boundSetOps  // 操作set
 * redistempalate.boundListOps // 操作list
 * redistempalate.boundHashOps // 操作hash
 * redistempalate.boundZSetOps // 操作有序set
 */
@Component
public class RedisUtils {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private final static Logger log = LoggerFactory.getLogger(RedisUtils.class);

    /** redis String 增删改查***********************start*/

    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    public String get(final String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 写入缓存
     */
    public boolean set(final String key, String value, long expireSecond) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().set(key, value);
            if (expireSecond > 0) {
                redisTemplate.expire(key, expireSecond, TimeUnit.SECONDS);
            }
            result = true;
        } catch (Exception e) {
            log.info("Redis:{}","setString error");
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 更新缓存
     */
    public boolean getAndSet(final String key, String value, long expireSecond) {
        boolean result = false;
        try {
            redisTemplate.opsForValue().getAndSet(key, value);
            if (expireSecond > 0) {
                redisTemplate.expire(key, expireSecond, TimeUnit.SECONDS);
            }
            result = true;
        } catch (Exception e) {
            log.info("Redis:{}","getAndSetString error");
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 删除缓存
     */
    public boolean delete(final String key) {
        boolean result = false;
        try {
            redisTemplate.delete(key);
            result = true;
        } catch (Exception e) {
            log.info("Redis:{}","deleteString error");
            e.printStackTrace();
        }
        return result;
    }


    /** redis list 增删改查***********************start*/

    /**
     * 添加一个集合对象
     * 右压栈：后添加的对象排在后边，相当于队列，相当于先进先出
     * @param key
     * @param value
     *
     */
    public void addRightList(String key, String value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
        } catch (Exception e) {
            log.info("Redis:{}","addRightList error");
            e.printStackTrace();
        }
    }

    /**
     * 添加一个集合对象
     * 左压栈：后添加的对象排在前边,相当于栈，先进后出
     * @param key
     * @param value
     *
     */
    public void addLeftList(String key, String value) {
        try {
            redisTemplate.opsForList().leftPush(key, value);
        } catch (Exception e) {
            log.info("Redis:{}","addLeftList error");
            e.printStackTrace();
        }
    }

    /**
     * 获取list
     * @param key
     * @param start 开始
     * @param end 结束
     * @return
     * 区间以偏移量 start 和 end 指定。 其中 0 表示列表的第一个元素，
     * 1 表示列表的第二个元素，以此类推。 你也可以使用负数下标，以 -1 表示列表的最后一个元素，
     * -2 表示列表的倒数第二个元素，以此类推
     */
    public List<String> getList(String key, int start, int end){
        List<String> list = null;
        try {
            //获取指定长度的list集合
            list = redisTemplate.boundListOps(key).range(start, end);
        } catch (Exception e) {
            log.info("Redis:{}","getList error");
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 查询List
     * @param key
     * @param index 索引
     * 查询集合某个元素
     */
    public String getListByIndex(String key, int index){
        String str = null;
        try {
            str = redisTemplate.boundListOps(key).index(index);
        } catch (Exception e) {
            log.info("Redis:{}","getListByIndex error");
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 删除List
     * @param key
     * @param count
     * @param value
     * 移除集合某个元素,其中remove中第一个参数是移除的个数
     */
    public void removeListValue(String key, int count, String value){
        try {
            redisTemplate.boundListOps(key).remove(count, value);
        } catch (Exception e) {
            log.info("Redis:{}","removeListValue error");
            e.printStackTrace();
        }
    }
}